package com.huawang.mdesign.model.service.inter;

import com.huawang.business.dto.graph.ModelInfo;
import com.huawang.business.dto.property.ItemInfo;
import com.huawang.business.service.model.base.UmlService;
import com.huawang.business.service.model.core.InternalUmlService;
import com.huawang.business.service.model.core.ModelPropertyInfoService;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.cmof.reflection.impl.BasicRObject;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.core.semantics.entity.MofPropertyInfo;
import com.huawang.core.semantics.utils.TransformUtil;
import com.huawang.mdesign.model.service.vo.ExchangeInformationFlowVo;
import com.huawang.mdesign.model.service.vo.ExchangeSendingReceivingVo;
import lombok.Data;
import lombok.extern.java.Log;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 信息流服务类
 */
@Service
@Primary
@Log
public class InformationFlowService {
    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private UmlService umlService;

    @Autowired
    private UAFExchangeService uafExchangeService;

    @Autowired
    private ModelPropertyInfoService modelPropertyInfoService;

    @Data
    private static class SendingAndReceivingEnd {
        private Set<MetaClassInstance> sendingEnds = new HashSet<>();
        private Set<MetaClassInstance> receivingEnds = new HashSet<>();
    }

    /**
     * 获得关系两端的类型
     *
     */
    @NotNull
    private SendingAndReceivingEnd getSendingAndReceivingEnds(String projectId, MetaClassInstance relation) {
        SendingAndReceivingEnd sendingAndReceivingEnd = new SendingAndReceivingEnd();
        if (relation != null) {
            Set<MetaClassInstance> sourceEndTypes = sendingAndReceivingEnd.getSendingEnds();
            Set<MetaClassInstance> targetEndTypes = sendingAndReceivingEnd.getReceivingEnds();
            if (UMLDefinitionConstants.Connector.equals(relation.getMetaClass().getId())) {
                List<MetaClassInstance> connectorEnd = internalUmlService.queryListInstanceProperty(projectId, relation, UMLDefinitionConstants.Connector_end);
                Optional.of(connectorEnd).filter(ends -> ends.size() > 1).ifPresent(ends -> {
                    MetaClassInstance type = getConnectorEndRoleType(projectId, connectorEnd.get(0));
                    Optional.ofNullable(type).ifPresent(sourceEndTypes::add);
                    type = getConnectorEndRoleType(projectId, connectorEnd.get(1));
                    Optional.ofNullable(type).ifPresent(targetEndTypes::add);
                });
            } else if (UMLDefinitionConstants.Message.equals(relation.getMetaClass().getId())) {
                MetaClassInstance event = internalUmlService.queryInstanceProperty(projectId, relation, UMLDefinitionConstants.Message_sendEvent);
                MetaClassInstance type = getMessageEndType(projectId, event);
                if(event != null) {
                    sourceEndTypes.add(type);
                }
                event = internalUmlService.queryInstanceProperty(projectId, relation, UMLDefinitionConstants.Message_receiveEvent);
                type = getMessageEndType(projectId, event);
                if(type != null) {
                    targetEndTypes.add(type);
                }
            } else if (UMLDefinitionConstants.Association.equals(relation.getMetaClass().getId())) {
                List<MetaClassInstance> endTypes = internalUmlService.queryListInstanceProperty(projectId, relation,
                        UMLDefinitionConstants.Association_endType);
                Optional.of(endTypes).filter(types -> types.size() == 1).ifPresent(types -> {
                    sourceEndTypes.add(endTypes.get(0));
                    targetEndTypes.add(endTypes.get(0));
                });
                Optional.of(endTypes).filter(types -> types.size() == 2).ifPresent(types -> {
                    sourceEndTypes.add(endTypes.get(1));
                    targetEndTypes.add(endTypes.get(0));
                });
            } else if (internalUmlService.checkInstanceType(projectId, relation, UMLDefinitionConstants.ActivityEdge)) {
                updateSendingAndReceivingEndByActivityEdge(projectId, relation, sourceEndTypes, targetEndTypes);
            } else {
                return sendingAndReceivingEnd;
            }
        }
        return sendingAndReceivingEnd;
    }

    /**
     * 根据活动边，来获得发送和接受模型列表
     *
     * @param projectId
     * @param relation
     * @param sourceEndTypes
     * @param targetEndTypes
     */
    private void updateSendingAndReceivingEndByActivityEdge(String projectId, MetaClassInstance relation, Set<MetaClassInstance> sourceEndTypes, Set<MetaClassInstance> targetEndTypes) {
        MetaClassInstance sourceActivityNode = uafExchangeService.getSourceActivityNodeFromActivityEdge(projectId, relation);
        MetaClassInstance targetActivityNode = uafExchangeService.getTargetActivityNodeFromActivityEdge(projectId, relation);
        if (sourceActivityNode != null && targetActivityNode != null) {
            Set<String> sourceActivityNodeTypes = internalUmlService.getGivenTypes(projectId, sourceActivityNode);
            Set<String> targetActivityNodeTypes = internalUmlService.getGivenTypes(projectId, targetActivityNode);
            if (sourceActivityNodeTypes.contains(UMLDefinitionConstants.ControlNode) && (targetActivityNodeTypes.contains(UMLDefinitionConstants.CallBehaviorAction) || targetActivityNodeTypes.contains(UMLDefinitionConstants.ActivityParameterNode))) {
                // 起始端为控制节点，目标端为对象节点
                getFirstCallBehaviorActionOrActivityParameterNode(projectId, sourceActivityNode, false, new HashSet<>()).forEach(activityNode -> sourceEndTypes.addAll(getActivityEdgeEndList(projectId, activityNode)));
                targetEndTypes.addAll(getActivityEdgeEndList(projectId, targetActivityNode));
            } else if ((sourceActivityNodeTypes.contains(UMLDefinitionConstants.CallBehaviorAction) || sourceActivityNodeTypes.contains(UMLDefinitionConstants.ActivityParameterNode)) && targetActivityNodeTypes.contains(UMLDefinitionConstants.ControlNode)) {
                // 起始端为对象节点，目标端为控制节点
                sourceEndTypes.addAll(getActivityEdgeEndList(projectId, sourceActivityNode));
                getFirstCallBehaviorActionOrActivityParameterNode(projectId, targetActivityNode, true, new HashSet<>()).forEach(activityNode -> targetEndTypes.addAll(getActivityEdgeEndList(projectId, activityNode)));
            } else if ((sourceActivityNodeTypes.contains(UMLDefinitionConstants.CallBehaviorAction) || sourceActivityNodeTypes.contains(UMLDefinitionConstants.ActivityParameterNode)) &&
                    (targetActivityNodeTypes.contains(UMLDefinitionConstants.CallBehaviorAction) || targetActivityNodeTypes.contains(UMLDefinitionConstants.ActivityParameterNode))) {
                sourceEndTypes.addAll(getActivityEdgeEndList(projectId, sourceActivityNode));
                targetEndTypes.addAll(getActivityEdgeEndList(projectId, targetActivityNode));
            } else if (sourceActivityNodeTypes.contains(UMLDefinitionConstants.ControlNode) && targetActivityNodeTypes.contains(UMLDefinitionConstants.ControlNode)) {
                // 起始端为控制节点，目标端为控制节点
                getFirstCallBehaviorActionOrActivityParameterNode(projectId, sourceActivityNode, false, new HashSet<>()).forEach(activityNode -> sourceEndTypes.addAll(getActivityEdgeEndList(projectId, activityNode)));
                getFirstCallBehaviorActionOrActivityParameterNode(projectId, targetActivityNode, true, new HashSet<>()).forEach(activityNode -> targetEndTypes.addAll(getActivityEdgeEndList(projectId, activityNode)));
            } else {
                log.info("sending and receiving models not found.");
            }
        }
    }

    /**
     * 获得message两端的类型
     *
     */
    @Nullable
    private MetaClassInstance getMessageEndType(String projectId, MetaClassInstance eventEnd) {
        if (eventEnd != null && UMLDefinitionConstants.MessageOccurrenceSpecification.equals(eventEnd.getMetaClass().getId())) {
            MetaClassInstance covered = internalUmlService.queryInstanceProperty(projectId, eventEnd, UMLDefinitionConstants.OccurrenceSpecification_covered);
            if (Objects.nonNull(covered)) {
                MetaClassInstance represents = internalUmlService.queryInstanceProperty(projectId, covered, UMLDefinitionConstants.Lifeline_represents);
                if (represents != null) {
                    return internalUmlService.queryInstanceProperty(projectId, represents, UMLDefinitionConstants.TypedElement_type);
                }
            }
        }
        return null;
    }

    /**
     * 根据ConnectorEnd，获得对应的Role的类型
     *
     */
    @Nullable
    private MetaClassInstance getConnectorEndRoleType(String projectId, MetaClassInstance connectorEnd) {
        if (connectorEnd != null) {
            MetaClassInstance connectorEndRole = internalUmlService.queryInstanceProperty(projectId, connectorEnd,
                    UMLDefinitionConstants.ConnectorEnd_role);
            if (Objects.isNull(connectorEndRole)){
                return null;
            }
            if (UMLDefinitionConstants.Property.equals(connectorEndRole.getMetaClass().getId())) {
                return internalUmlService.queryInstanceProperty(projectId, connectorEndRole, UMLDefinitionConstants.TypedElement_type);
            } else if(UMLDefinitionConstants.Port.equals(connectorEndRole.getMetaClass().getId())) {
                return internalUmlService.queryInstanceProperty(projectId, connectorEndRole, UMLDefinitionConstants.Element_owner);
            } else {
                return null;
            }
        }
        return null;
    }

    /**
     * 根据关系，获取信息流两端的可用元素
     *
     */
    @NotNull
    public ExchangeSendingReceivingVo querySendingAndReceiving(String projectId, String exchangeTypeId, String relationId) {
        ExchangeSendingReceivingVo exchangeSendingReceivingVo = new ExchangeSendingReceivingVo();
        if(StringUtils.isNotBlank(relationId)) {
            MetaClassInstance relationInstance = internalUmlService.fetchInstance(relationId, projectId);
            if (relationInstance != null && !relationInstance.getAppliedStereotypes().isEmpty()) {
                getExchangeSendingReceivingVoByRelation(projectId, exchangeTypeId, relationInstance, exchangeSendingReceivingVo);
            }
        } else {
            getExchangeSendingReceivingVoWithoutRelation(projectId, exchangeTypeId, exchangeSendingReceivingVo);
        }

        return exchangeSendingReceivingVo;
    }

    /**
     * 获得符合转换两端的所有类型
     *
     * @param projectId
     * @param exchangeTypeId
     * @param exchangeSendingReceivingVo
     */
    private void getExchangeSendingReceivingVoWithoutRelation(String projectId, String exchangeTypeId,
                                                         ExchangeSendingReceivingVo exchangeSendingReceivingVo) {
        List<MetaClassInstance> instances;
        if (UMLDefinitionConstants.UAF_OperationalExchange.equals(exchangeTypeId)) {
            instances = internalUmlService.querySpecifiedInstanceList(projectId, UMLDefinitionConstants.UAF_OperationalAgent, false);

        } else if (UMLDefinitionConstants.UAF_ResourceExchange.equals(exchangeTypeId)) {
            instances = internalUmlService.querySpecifiedInstanceList(projectId, UMLDefinitionConstants.UAF_ResourcePerformer, false);
        } else if (UMLDefinitionConstants.UAF_ServiceExchange.equals(exchangeTypeId)) {
            instances = internalUmlService.querySpecifiedInstanceList(projectId, UMLDefinitionConstants.UAF_Service, false);
        } else {
            log.info("不支持的转换类型" + exchangeTypeId);
            return;
        }
        if(CollectionUtils.isNotEmpty(instances)) {
            exchangeSendingReceivingVo.setSendings(generateItemInfos(projectId, instances));
            exchangeSendingReceivingVo.setReceivings(exchangeSendingReceivingVo.getSendings());
        }
    }



    /**
     * 根据关系查询转换两端的类型
     *
     * @param projectId
     * @param exchangeTypeId
     * @param relationInstance
     * @param exchangeSendingReceivingVo
     */
    private void getExchangeSendingReceivingVoByRelation(String projectId, String exchangeTypeId, MetaClassInstance relationInstance,
                                                          ExchangeSendingReceivingVo exchangeSendingReceivingVo) {
        SendingAndReceivingEnd sendingAndReceivingEnd = getSendingAndReceivingEnds(projectId, relationInstance);
        if (UMLDefinitionConstants.UAF_OperationalExchange.equals(exchangeTypeId)) {
            exchangeSendingReceivingVo.setSendings(filterAndConvertEndType(projectId, relationInstance, sendingAndReceivingEnd.getSendingEnds(), UMLDefinitionConstants.UAF_OperationalAgent));
            exchangeSendingReceivingVo.setReceivings(filterAndConvertEndType(projectId, relationInstance, sendingAndReceivingEnd.getReceivingEnds(), UMLDefinitionConstants.UAF_OperationalAgent));
        } else if (UMLDefinitionConstants.UAF_ResourceExchange.equals(exchangeTypeId)) {
            exchangeSendingReceivingVo.setSendings(filterAndConvertEndType(projectId, relationInstance, sendingAndReceivingEnd.getSendingEnds(), UMLDefinitionConstants.UAF_ResourcePerformer));
            exchangeSendingReceivingVo.setReceivings(filterAndConvertEndType(projectId, relationInstance, sendingAndReceivingEnd.getReceivingEnds(), UMLDefinitionConstants.UAF_ResourcePerformer));
        } else if (UMLDefinitionConstants.UAF_ServiceExchange.equals(exchangeTypeId)) {
            exchangeSendingReceivingVo.setSendings(filterAndConvertEndType(projectId, relationInstance, sendingAndReceivingEnd.getSendingEnds(), UMLDefinitionConstants.UAF_Service));
            exchangeSendingReceivingVo.setReceivings(filterAndConvertEndType(projectId, relationInstance, sendingAndReceivingEnd.getReceivingEnds(), UMLDefinitionConstants.UAF_Service));
        } else {
            log.info("不支持的转换类型" + exchangeTypeId);
        }
    }

    /**
     * 根据起始点遍历到第一个UAF的CallBehaviorAction或ActivityParameterNode返回，期间过滤掉控制节点
     *
     */
    @NotNull
    private Set<MetaClassInstance> getFirstCallBehaviorActionOrActivityParameterNode(String projectId, MetaClassInstance start, boolean sourceToTarget, Set<String> visitedActivityNode) {
        Set<MetaClassInstance> availableNodes = new HashSet<>();
        if (start != null) {
            if (visitedActivityNode.contains(start.getUUID())) {
                return availableNodes;
            }
            visitedActivityNode.add(start.getUUID());
            List<MetaClassInstance> edges = uafExchangeService.getActivityEdgesByActivityNode(projectId, start, sourceToTarget);
            MetaClassInstance activityNode;
            for (MetaClassInstance edge : edges) {
                activityNode = uafExchangeService.getActivityNodeByActivityEdge(projectId, edge, sourceToTarget);
                if (internalUmlService.checkInstanceType(projectId, activityNode, UMLDefinitionConstants.ControlNode)) {
                    //如果是控制节点，则继续查询下去
                    availableNodes.addAll(getFirstCallBehaviorActionOrActivityParameterNode(projectId, activityNode, sourceToTarget, visitedActivityNode));
                } else {
                    //非控制节点，则需要判断是否为UAF的CallBehaviorAction/ActivityParameterNode
                    if(uafExchangeService.isActionRelatedToBehavior(projectId, activityNode)) {
                        availableNodes.add(activityNode);
                    }
                }
            }
        }
        return availableNodes;
    }

    /**
     * 根据条件过滤并转换端的类型
     *
     */
    @NotNull
    private List<ItemInfo> filterAndConvertEndType(String projectId, MetaClassInstance relationInstance, Set<MetaClassInstance> endTypes, String filterType) {
        List<ItemInfo> newEndTypes = new ArrayList<>();
        if (endTypes != null) {
            endTypes.stream().filter(sourceType -> internalUmlService.checkInstanceType(projectId, sourceType, filterType)).forEach(sourceType -> {
                ItemInfo itemInfo = generateItemInfo(projectId, sourceType);
                if (itemInfo != null) {
                    newEndTypes.add(itemInfo);
                }
            });
        }
        // 如果是Connector和Message的关系，并且对应的ConnectorEnd没有类型，则把项目中所有指定的类型都显示出来
        if (UMLDefinitionConstants.Connector.equals(relationInstance.getMetaClass().getId()) && newEndTypes.isEmpty() ||
                UMLDefinitionConstants.Message.equals(relationInstance.getMetaClass().getId()) && newEndTypes.isEmpty()) {
            internalUmlService.querySpecifiedInstanceList(projectId, filterType).forEach(instance -> {
                ItemInfo itemInfo = generateItemInfo(projectId, instance);
                if (itemInfo != null) {
                    newEndTypes.add(itemInfo);
                }
            });
        }
        return newEndTypes;
    }

    /**
     * 根据实例生成ItemInfo
     *
     */
    @Nullable
    private ItemInfo generateItemInfo(String projectId, MetaClassInstance instance) {
        ItemInfo itemInfo = null;
        ModelInfo info = internalUmlService.fetchModelInfoValue(projectId, instance);
        if (info != null) {
            itemInfo = new ItemInfo();
            itemInfo.setValue(instance.getUUID());
            itemInfo.setLabel(internalUmlService.queryStringProperty(projectId, instance, UMLDefinitionConstants.NamedElement_name));
            itemInfo.setEnLabel(itemInfo.getLabel());
            itemInfo.setIcon(info.getIcon());
        }
        return itemInfo;
    }

    /**
     * 根据实例列表生成ItemInfo列表
     *
     */
    @NotNull
    private List<ItemInfo> generateItemInfos(String projectId, List<MetaClassInstance> instances) {
        List<ItemInfo> itemInfos = new ArrayList<>(instances.size());
        modelPropertyInfoService.createModelPropertyInfoList(projectId, instances, Collections.singletonList(UMLDefinitionConstants.NamedElement_name))
                .forEach(modelPropertyInfo -> {
                    ModelInfo info = internalUmlService.fetchModelInfoValue(projectId, modelPropertyInfo.getInstance());
                    if (info != null) {
                        ItemInfo itemInfo = new ItemInfo();
                        itemInfo.setValue(modelPropertyInfo.getInstanceId());
                        itemInfo.setLabel(modelPropertyInfo.queryStringValue(UMLDefinitionConstants.NamedElement_name));
                        itemInfo.setEnLabel(itemInfo.getLabel());
                        itemInfo.setIcon(info.getIcon());
                        itemInfos.add(itemInfo);
                    }
                });
        return itemInfos;
    }

    /**
     * 获得活动边的两端类型
     *
     * @param projectId
     * @param activityNode
     * @return
     */
    @NotNull
    private Set<MetaClassInstance> getActivityEdgeEndList(String projectId, MetaClassInstance activityNode) {
        Set<MetaClassInstance> endTypes = new HashSet<>();
        Optional.ofNullable(activityNode).ifPresent(end -> {
            if (UMLDefinitionConstants.CallBehaviorAction.equals(end.getMetaClass().getId())) {
                // 1. 优先找到这个Action所在的ActivityPartition
                MetaClassInstance inPartition = internalUmlService.queryListInstanceProperty(projectId, end, UMLDefinitionConstants.ActivityNode_inPartition).stream().filter(partition ->
                        internalUmlService.queryListInstanceProperty(projectId, partition, UMLDefinitionConstants.ActivityPartition_subpartition).isEmpty()
                ).findFirst().orElse(null);
                Optional.ofNullable(inPartition).ifPresent(p -> {
                    MetaClassInstance represents = getRepresentRecursively(projectId, p);
                    if (represents != null) {
                        represents = internalUmlService.queryInstanceProperty(projectId, represents, UMLDefinitionConstants.TypedElement_type);
                        if (represents != null && UMLDefinitionConstants.Class.equals(represents.getMetaClass().getId())) {
                            endTypes.add(represents);
                        }
                    }
                });
                // 2. 其次如果没有被ActivityPartition，则通过CallBehavior找Behavior属性的行为，并能执行这个行为的模型
                Optional.of(endTypes).filter(Set::isEmpty).ifPresent(e -> {
                    MetaClassInstance behavior = internalUmlService.queryInstanceProperty(projectId, end, UMLDefinitionConstants.CallBehaviorAction_behavior);
                    endTypes.addAll(getModelCanPerformBehavior(projectId, behavior));
                });
            } else if (UMLDefinitionConstants.ActivityParameterNode.equals(end.getMetaClass().getId())) {
                MetaClassInstance activity = internalUmlService.queryInstanceProperty(projectId, end, UMLDefinitionConstants.ActivityNode_activity);
                endTypes.addAll(getModelCanPerformBehavior(projectId, activity));
            } else {
                log.info("endTypes is empty.");
            }
        });
        return endTypes;
    }

    /**
     * 获得可用执行指定行为的模型列表
     *
     */
    @NotNull
    private List<MetaClassInstance> getModelCanPerformBehavior(String projectId, MetaClassInstance behavior) {
        List<MetaClassInstance> models = new ArrayList<>();
        if (behavior != null) {
            internalUmlService.queryListInstanceProperty(projectId, behavior, UMLDefinitionConstants.A_supplier_supplierDependency_supplierDependency).stream().filter(supplier ->
                 supplier.getAppliedStereotypes().contains(UMLDefinitionConstants.UAF_IsCapableToPerform)
            ).forEach(isCapableToPerform ->
                models.addAll(internalUmlService.queryListInstanceProperty(projectId, isCapableToPerform, UMLDefinitionConstants.DirectedRelationship_source))
            );
        }
        return models;
    }

    /**
     * 递归获取代表
     *
     */
    @Nullable
    private MetaClassInstance getRepresentRecursively(String projectId, MetaClassInstance partition) {
        MetaClassInstance represent = internalUmlService.queryInstanceProperty(projectId, partition, UMLDefinitionConstants.ActivityPartition_represents);
        if (represent == null) {
            MetaClassInstance superPartition = internalUmlService.queryInstanceProperty(projectId, partition, UMLDefinitionConstants.ActivityPartition_superPartition);
            if (superPartition != null) {
                represent = getRepresentRecursively(projectId, superPartition);
            }
        }
        return represent;
    }

    /**
     * 根据关系，获取信息流列表
     *
     */
    @NotNull
    public List<ExchangeInformationFlowVo> queryInformationFlowByRelation(String projectId, String exchangeTypeId, String exchangeKind, String relationId) {
        MetaClassInstance relation = internalUmlService.fetchInstance(relationId, projectId);
        if (relation != null) {
            SendingAndReceivingEnd sendingAndReceivingEnd = getSendingAndReceivingEnds(projectId, relation);
            boolean hasSendingAndReceiving = !sendingAndReceivingEnd.getReceivingEnds().isEmpty() &&
                    !sendingAndReceivingEnd.getSendingEnds().isEmpty();
            if (hasSendingAndReceiving) {
                // 1. 获得与关联的InformationFlow列表
                List<MetaClassInstance> informationFlows = getRealizedInformationFlow(projectId, relation);

                //关系是否有方向标记
                boolean relationHasDirection = !UMLDefinitionConstants.Connector.equals(relation.getMetaClass().getId()) && (!UMLDefinitionConstants.Association.equals(relation.getMetaClass().getId()) ||
                        !internalUmlService.queryListInstanceProperty(projectId, relation, UMLDefinitionConstants.Association_ownedEnd).isEmpty());
                return getExchangeInformationFlowVo(projectId, relationHasDirection, exchangeTypeId, sendingAndReceivingEnd, exchangeKind, informationFlows);
            }
        }
        return Collections.emptyList();
    }

    /**
     * 获得InformationFlow列表
     *
     * @param projectId
     * @param relationHasDirection
     * @param exchangeTypeId
     * @param sendingAndReceivingEnd
     * @param exchangeKind
     * @param informationFlows
     * @return
     */
    @NotNull
    private List<ExchangeInformationFlowVo> getExchangeInformationFlowVo(String projectId, boolean relationHasDirection, String exchangeTypeId,
                                                                         SendingAndReceivingEnd sendingAndReceivingEnd, String exchangeKind, List<MetaClassInstance> informationFlows) {
        List<ExchangeInformationFlowVo> list = new ArrayList<>();

        // 1. 遍历所有指定类型的转换，并获得可以被关联到指定关系的所有InformationFlow
        List<MetaClassInstance> exchanges = internalUmlService.querySpecifiedInstanceList(projectId, exchangeTypeId);
        List<String> propertyKeys = Stream.of(UMLDefinitionConstants.InformationFlow_informationSource, UMLDefinitionConstants.InformationFlow_informationTarget,
                UMLDefinitionConstants.InformationFlow_conveyed).collect(Collectors.toList());
        Map<String, Map<String, MofPropertyInfo>> instancePropertyInfoMap = internalUmlService.queryPropertyByModelKeyMap(projectId, exchanges.stream().collect(Collectors.toMap(it -> it,
                it -> propertyKeys,
                (s, a) -> a))).getMofPropertyInfoMap();

        exchanges.forEach(exchange -> {
            Map<String, MofPropertyInfo> propertyInfoMapT = instancePropertyInfoMap.get(exchange.getUUID());
            Optional.ofNullable(propertyInfoMapT).ifPresent(propertyInfoMap -> {
                List<MetaClassInstance> conveyed = TransformUtil.transformObjectToListInstance(propertyInfoMap.get(UMLDefinitionConstants.InformationFlow_conveyed).getValues());
                List<MetaClassInstance> informationSources = TransformUtil.transformObjectToListInstance(propertyInfoMap.get(UMLDefinitionConstants.InformationFlow_informationSource).getValues());
                List<MetaClassInstance> informationTargets = TransformUtil.transformObjectToListInstance(propertyInfoMap.get(UMLDefinitionConstants.InformationFlow_informationTarget).getValues());
                MetaClassInstance informationSource = informationSources.isEmpty() ? null : informationSources.get(0);
                MetaClassInstance informationTarget = informationTargets.isEmpty() ? null : informationTargets.get(0);
                // 如果关系是有方向的，怎只能从source->target查找InformationFlow，否则都需要双向查询
                if (relationHasDirection) {
                    Optional.ofNullable(sendingAndReceivingEnd).filter(end -> end.getSendingEnds().contains(informationSource) && end.getReceivingEnds().contains(informationTarget)).ifPresent(end -> {
                        ExchangeInformationFlowVo exchangeInformationFlowVo = convertExchangeToVo(projectId, exchange, informationSource, informationTarget, conveyed, informationFlows);
                        addInformationFlowToList(exchangeKind, exchange, exchangeInformationFlowVo, list);
                    });
                } else {
                    Optional.ofNullable(sendingAndReceivingEnd).filter(end -> (end.getSendingEnds().contains(informationSource) && end.getReceivingEnds().contains(informationTarget)) ||
                            (end.getSendingEnds().contains(informationTarget) && end.getReceivingEnds().contains(informationSource))).ifPresent(end -> {
                        ExchangeInformationFlowVo exchangeInformationFlowVo = convertExchangeToVo(projectId, exchange, informationSource, informationTarget, conveyed, informationFlows);
                        addInformationFlowToList(exchangeKind, exchange, exchangeInformationFlowVo, list);
                    });
                }
            });
        });
        return list;
    }

    /**
     * 将InformationFlow加入到指定的列表中
     *
     * @param exchangeKind
     * @param exchange
     * @param exchangeInformationFlowVo
     * @param list
     */
    private void addInformationFlowToList(String exchangeKind, MetaClassInstance exchange, ExchangeInformationFlowVo exchangeInformationFlowVo, List<ExchangeInformationFlowVo> list) {
        if (StringUtils.isEmpty(exchangeKind) || exchange.getUUID().equals(exchangeInformationFlowVo.getExchangeKind())) {
            list.add(exchangeInformationFlowVo);
        }
    }

    /**
     * 将Exchange模型转换为VO
     *
     */
    @NotNull
    private ExchangeInformationFlowVo convertExchangeToVo(String projectId, MetaClassInstance exchange, MetaClassInstance informationSource, MetaClassInstance informationTarget,
                                                          List<MetaClassInstance> conveyed, List<MetaClassInstance> informationFlows) {
        ExchangeInformationFlowVo exchangeInformationFlowVo = new ExchangeInformationFlowVo();
        exchangeInformationFlowVo.setExchangeId(exchange.getUUID());
        if (informationSource != null) {
            exchangeInformationFlowVo.setSendingId(informationSource.getUUID());
        }
        if (informationTarget != null) {
            exchangeInformationFlowVo.setReceivingId(informationTarget.getUUID());
        }
        exchangeInformationFlowVo.setConveyed(conveyed.stream().map(BasicRObject::getUUID).collect(Collectors.toList()));
        MetaClassInstance exchangeKind;
        if (exchange.getAppliedStereotypes().contains(UMLDefinitionConstants.UAF_OperationalExchange)) {
            exchangeKind = internalUmlService.queryInstanceProperty(projectId, exchange, UMLDefinitionConstants.UAF_OperationalExchange_exchangeKind);
        } else if (exchange.getAppliedStereotypes().contains(UMLDefinitionConstants.UAF_ResourceExchange)) {
            exchangeKind = internalUmlService.queryInstanceProperty(projectId, exchange, UMLDefinitionConstants.UAF_ResourceExchange_exchangeKind);
        } else if (exchange.getAppliedStereotypes().contains(UMLDefinitionConstants.UAF_ServiceExchange)) {
            exchangeKind = internalUmlService.queryInstanceProperty(projectId, exchange, UMLDefinitionConstants.UAF_ServiceExchange_exchangeKind);
        } else {
            exchangeKind = null;
        }
        if (exchangeKind != null) {
            exchangeInformationFlowVo.setExchangeKind(exchangeKind.getUUID());
        }
        if (informationFlows.contains(exchange)) {
            exchangeInformationFlowVo.setRealize(true);
        }
        return exchangeInformationFlowVo;
    }

    /**
     * 获得与指定关系关联的InformationFlow
     *
     */
    @NotNull
    private List<MetaClassInstance> getRealizedInformationFlow(String projectId, MetaClassInstance relation) {
        List<MetaClassInstance> informationFlows = new ArrayList<>();
        if (UMLDefinitionConstants.Association.equals(relation.getMetaClass().getId())) {
            informationFlows.addAll(internalUmlService.queryListInstanceProperty(projectId, relation,
                    UMLDefinitionConstants.A_realization_abstraction_flow_abstraction));
        } else if (UMLDefinitionConstants.Connector.equals(relation.getMetaClass().getId())) {
            informationFlows.addAll(internalUmlService.queryListInstanceProperty(projectId,
                    relation, UMLDefinitionConstants.A_realizingConnector_informationFlow_informationFlow));
        } else if (internalUmlService.checkInstanceType(projectId, relation, UMLDefinitionConstants.ActivityEdge)) {
            informationFlows.addAll(internalUmlService.queryListInstanceProperty(projectId,
                    relation, UMLDefinitionConstants.A_realizingActivityEdge_informationFlow_informationFlow));
        } else if (UMLDefinitionConstants.Message.equals(relation.getMetaClass().getId())) {
            informationFlows.addAll(internalUmlService.queryListInstanceProperty(projectId,
                    relation, UMLDefinitionConstants.A_realizingMessage_informationFlow_informationFlow));
        } else {
            return informationFlows;
        }
        return informationFlows;
    }

    /**
     * 根据删除的活动边，更新其对应的InformationFlow
     *
     */
    public void updateInformationFlowByDeletedActivityEdge(String projectId, MetaClassInstance activityEdge) {
        List<MetaClassInstance> informationFlows = internalUmlService.queryListInstanceProperty(projectId, activityEdge,
                UMLDefinitionConstants.A_realizingActivityEdge_informationFlow_informationFlow);
        if (CollectionUtils.isEmpty(informationFlows)) {
            return;
        }
        List<String> informationPropertyKeys = Stream.of(UMLDefinitionConstants.InformationFlow_realizingActivityEdge).collect(Collectors.toList());
        List<String> activityEdgePropertyKeys = Stream.of(UMLDefinitionConstants.ActivityEdge_source, UMLDefinitionConstants.ActivityEdge_target).collect(Collectors.toList());
        Map<String, Map<String, MofPropertyInfo>> informationPropertyInfoMap = internalUmlService.queryPropertyByModelKeyMap(projectId, informationFlows.stream().collect(Collectors.toMap(it -> it,
                it -> informationPropertyKeys,
                (s, a) -> a))).getMofPropertyInfoMap();
        Map<String, MofPropertyInfo> informationPropertyInfo;
        for(MetaClassInstance informationFlow : informationFlows) {
            informationPropertyInfo = informationPropertyInfoMap.get(informationFlow.getUUID());
            if(informationPropertyInfo != null) {
                List<MetaClassInstance> newRealizingActivityEdges = new ArrayList<>();
                List<MetaClassInstance> realizingActivityEdges = TransformUtil.transformObjectToListInstance(informationPropertyInfo.get(UMLDefinitionConstants.InformationFlow_realizingActivityEdge).getValues());
                realizingActivityEdges.remove(activityEdge);
                Map<String, Map<String, MofPropertyInfo>> activityEdgePropertyInfoMap = internalUmlService.queryPropertyByModelKeyMap(projectId, realizingActivityEdges.stream().collect(Collectors.toMap(it -> it,
                        it -> activityEdgePropertyKeys,
                        (s, a) -> a))).getMofPropertyInfoMap();
                Map<String, ActivityEdgeWithCallBehaviorActionOrActivityParameterNode> activityEdgeMap = initWithActivityEdges(projectId, realizingActivityEdges, activityEdgePropertyInfoMap);
                for(Map.Entry<String, ActivityEdgeWithCallBehaviorActionOrActivityParameterNode> entry : activityEdgeMap.entrySet()) {
                    boolean validUpstream = isValidActivityEdgeFromOneDirection(projectId, true, entry.getValue());
                    boolean validDownstream = isValidActivityEdgeFromOneDirection(projectId, false, entry.getValue());
                    if(validDownstream && validUpstream) {
                        newRealizingActivityEdges.add(entry.getValue().getEdge());
                    }
                }
                umlService.updateModel(projectId, informationFlow.getUUID(), UMLDefinitionConstants.InformationFlow_realizingActivityEdge, newRealizingActivityEdges);
            }
        }
    }

    @Data
    private static class ActivityEdgeWithCallBehaviorActionOrActivityParameterNode {
        private MetaClassInstance source;
        private MetaClassInstance target;
        private MetaClassInstance edge;
        private ActivityEdgeWithCallBehaviorActionOrActivityParameterNode preEdge;
        private ActivityEdgeWithCallBehaviorActionOrActivityParameterNode nextEdge;
        @Override
        public String toString() {
            return source.getUUID() + edge.getUUID() + target.getUUID();
        }
    }

    /**
     * 活动边的一个方向是否有效
     *
     */
    private boolean isValidActivityEdgeFromOneDirection(String projectId, boolean isSource, ActivityEdgeWithCallBehaviorActionOrActivityParameterNode edge) {
        if(isSource) {
            ActivityEdgeWithCallBehaviorActionOrActivityParameterNode preEdge = edge.preEdge;
            if(preEdge == null) {
                return uafExchangeService.isActionRelatedToBehavior(projectId, edge.getSource());
            } else {
                return isValidActivityEdgeFromOneDirection(projectId, true, preEdge);
            }
        } else {
            ActivityEdgeWithCallBehaviorActionOrActivityParameterNode nextEdge = edge.nextEdge;
            if(nextEdge == null) {
                return uafExchangeService.isActionRelatedToBehavior(projectId, edge.getTarget());
            } else {
                return isValidActivityEdgeFromOneDirection(projectId, false, nextEdge);
            }
        }
    }

    /**
     * 初始化活动边为内部模型，并将边按照顺序组装成链
     *
     */
    @NotNull
    private Map<String, ActivityEdgeWithCallBehaviorActionOrActivityParameterNode> initWithActivityEdges(String projectId, List<MetaClassInstance> realizingActivityEdges, Map<String, Map<String, MofPropertyInfo>> activityEdgePropertyInfoMap) {
        Map<String, ActivityEdgeWithCallBehaviorActionOrActivityParameterNode> reMap = new HashMap<>();
        //1. 初始化边
        realizingActivityEdges.forEach(realizingActivityEdge -> {
            Map<String, MofPropertyInfo> activityEdgePropertyInfo = activityEdgePropertyInfoMap.get(realizingActivityEdge.getUUID());
            if(activityEdgePropertyInfo != null) {
                ActivityEdgeWithCallBehaviorActionOrActivityParameterNode line = new ActivityEdgeWithCallBehaviorActionOrActivityParameterNode();
                line.setEdge(realizingActivityEdge);
                MetaClassInstance activityEdgeSource = TransformUtil.transformObjectToInstance(activityEdgePropertyInfo.get(UMLDefinitionConstants.ActivityEdge_source).getValues());
                if(UMLDefinitionConstants.InputPin.equals(activityEdgeSource.getMetaClass().getId()) || UMLDefinitionConstants.OutputPin.equals(activityEdgeSource.getMetaClass().getId())) {
                    line.setSource(internalUmlService.queryInstanceProperty(projectId, activityEdgeSource, UMLDefinitionConstants.Element_owner));
                } else {
                    line.setSource(activityEdgeSource);
                }
                MetaClassInstance activityEdgeTarget = TransformUtil.transformObjectToInstance(activityEdgePropertyInfo.get(UMLDefinitionConstants.ActivityEdge_target).getValues());
                if(UMLDefinitionConstants.InputPin.equals(activityEdgeTarget.getMetaClass().getId()) || UMLDefinitionConstants.OutputPin.equals(activityEdgeTarget.getMetaClass().getId())) {
                    line.setTarget(internalUmlService.queryInstanceProperty(projectId, activityEdgeTarget, UMLDefinitionConstants.Element_owner));
                } else {
                    line.setTarget(activityEdgeTarget);
                }
                reMap.put(realizingActivityEdge.getUUID(), line);
            }
        });
        //2. 边排序
        for(Map.Entry<String, ActivityEdgeWithCallBehaviorActionOrActivityParameterNode> entry : reMap.entrySet()) {
            ActivityEdgeWithCallBehaviorActionOrActivityParameterNode edge = entry.getValue();
            edge.setPreEdge(getActivityEdgeWithCallBehaviorActionOrActivityParameterNode(true, edge.getSource(), reMap));
            edge.setNextEdge(getActivityEdgeWithCallBehaviorActionOrActivityParameterNode(false, edge.getTarget(), reMap));
        }
        return reMap;
    }

    /**
     * 根据活动节点获得链节点
     *
     */
    @Nullable
    private ActivityEdgeWithCallBehaviorActionOrActivityParameterNode getActivityEdgeWithCallBehaviorActionOrActivityParameterNode(boolean source, MetaClassInstance activityNode,
                                                                                                                                   Map<String, ActivityEdgeWithCallBehaviorActionOrActivityParameterNode>map) {
        for(Map.Entry<String, ActivityEdgeWithCallBehaviorActionOrActivityParameterNode> entry : map.entrySet()) {
            ActivityEdgeWithCallBehaviorActionOrActivityParameterNode edge = entry.getValue();
            if(source) {
                if(edge.getTarget().equals(activityNode)) {
                    return edge;
                }
            } else {
                if(edge.getSource().equals(activityNode)) {
                    return edge;
                }
            }
        }
        return null;
    }

    /**
     * 活动边是否能关联信息流
     *
     */
    @NotNull
    public Boolean canActivityEdgeAttachInformationFlow(String projectId, String relationId) {
        MetaClassInstance relation = internalUmlService.fetchInstance(relationId, projectId);
        if (relation != null && (UMLDefinitionConstants.ObjectFlow.equals(relation.getMetaClass().getId()) || UMLDefinitionConstants.ControlFlow.equals(relation.getMetaClass().getId()))) {
            MetaClassInstance sourceActivityNode = uafExchangeService.getSourceActivityNodeFromActivityEdge(projectId, relation);
            MetaClassInstance targetActivityNode = uafExchangeService.getTargetActivityNodeFromActivityEdge(projectId, relation);
            if (sourceActivityNode != null && targetActivityNode != null) {
                Set<String> sourceActivityNodeTypes = internalUmlService.getGivenTypes(projectId, sourceActivityNode);
                Set<String> targetActivityNodeTypes = internalUmlService.getGivenTypes(projectId, targetActivityNode);

                if (isActivityNodeHasBehavior(projectId, sourceActivityNode, sourceActivityNodeTypes,
                        targetActivityNode, targetActivityNodeTypes)) {
                    return Boolean.TRUE;
                }
            }
        }
        return Boolean.FALSE;
    }

    /**
     * ActivityNode是否关联行为
     *
     * @param projectId
     * @param sourceActivityNode
     * @param sourceActivityNodeTypes
     * @param targetActivityNode
     * @param targetActivityNodeTypes
     * @return
     */
    private boolean isActivityNodeHasBehavior(String projectId, MetaClassInstance sourceActivityNode, Set<String> sourceActivityNodeTypes,
                                              MetaClassInstance targetActivityNode, Set<String> targetActivityNodeTypes) {
        Set<MetaClassInstance> availableSourceActivityNodes = new HashSet<>();
        Set<MetaClassInstance> availableTargetActivityNodes = new HashSet<>();
        if (sourceActivityNodeTypes.contains(UMLDefinitionConstants.ControlNode) && (targetActivityNodeTypes.contains(UMLDefinitionConstants.CallBehaviorAction) || targetActivityNodeTypes.contains(UMLDefinitionConstants.ActivityParameterNode))) {
            // 起始端为控制节点，目标端为对象节点
            availableSourceActivityNodes.addAll(getFirstCallBehaviorActionOrActivityParameterNode(projectId, sourceActivityNode, false, new HashSet<>()));
            Optional.of(targetActivityNode).filter(node -> uafExchangeService.isActionRelatedToBehavior(projectId, node)).ifPresent(availableTargetActivityNodes::add);
        } else if ((sourceActivityNodeTypes.contains(UMLDefinitionConstants.CallBehaviorAction) || sourceActivityNodeTypes.contains(UMLDefinitionConstants.ActivityParameterNode)) && targetActivityNodeTypes.contains(UMLDefinitionConstants.ControlNode)) {
            // 起始端为对象节点，目标端为控制节点
            Optional.of(sourceActivityNode).filter(node -> uafExchangeService.isActionRelatedToBehavior(projectId, node)).ifPresent(availableSourceActivityNodes::add);
            availableTargetActivityNodes.addAll(getFirstCallBehaviorActionOrActivityParameterNode(projectId, targetActivityNode, true, new HashSet<>()));
        } else if ((sourceActivityNodeTypes.contains(UMLDefinitionConstants.CallBehaviorAction) || sourceActivityNodeTypes.contains(UMLDefinitionConstants.ActivityParameterNode)) &&
                (targetActivityNodeTypes.contains(UMLDefinitionConstants.CallBehaviorAction) || targetActivityNodeTypes.contains(UMLDefinitionConstants.ActivityParameterNode))) {
            Optional.of(sourceActivityNode).filter(node -> uafExchangeService.isActionRelatedToBehavior(projectId, node)).ifPresent(availableSourceActivityNodes::add);
            Optional.of(targetActivityNode).filter(node -> uafExchangeService.isActionRelatedToBehavior(projectId, node)).ifPresent(availableTargetActivityNodes::add);
        } else if (sourceActivityNodeTypes.contains(UMLDefinitionConstants.ControlNode) && targetActivityNodeTypes.contains(UMLDefinitionConstants.ControlNode)) {
            // 起始端为控制节点，目标端为控制节点
            availableSourceActivityNodes.addAll(getFirstCallBehaviorActionOrActivityParameterNode(projectId, sourceActivityNode, false, new HashSet<>()));
            availableTargetActivityNodes.addAll(getFirstCallBehaviorActionOrActivityParameterNode(projectId, targetActivityNode, true, new HashSet<>()));
        } else {
            return false;
        }
        return !availableSourceActivityNodes.isEmpty() && !availableTargetActivityNodes.isEmpty();
    }
}
